Colormaps¶

This is a demo that replicates all the functionality displayed in https://niivue.github.io/niivue/features/colormaps.html.

In [1]:
from pathlib import Path

from ipyniivue import download_dataset

# GitHub API URL for the base folder
BASE_API_URL = "https://niivue.com/demos/images/"
DATA_FOLDER = Path("images")

# Download data for example
download_dataset(
    BASE_API_URL,
    DATA_FOLDER,
    files=[
        "mni152.nii.gz",
    ],
)
mni152.nii.gz already exists.
Dataset downloaded successfully to images.
In [2]:
import json
import math

import ipywidgets as widgets
from IPython.display import clear_output, display

from ipyniivue import NiiVue

# Create NiiVue instance
nv = NiiVue(back_color=(0.3, 0.3, 0.3, 1))

nv.load_volumes(
    [
        {
            "path": DATA_FOLDER / "mni152.nii.gz",
            "colormap": "gray",
            "opacity": 1,
        }
    ]
)

nv.opts.is_colorbar = True

# create the interactive controls

# Invert Checkbox
invert_check = widgets.Checkbox(value=False, description="Invert")


def on_invert_change(change):
    """Set colormap invert."""
    nv.volumes[0].colormap_invert = change["new"]


invert_check.observe(on_invert_change, names="value")

# Green Dragging Selection Checkbox
select_check = widgets.Checkbox(value=False, description="Green Dragging Selection")


def on_select_change(change):
    """Set selection box color."""
    if change["new"]:
        nv.set_selection_box_color((0, 1, 0, 0.7))
    else:
        nv.set_selection_box_color((1, 1, 1, 0.5))


select_check.observe(on_select_change, names="value")

# Green Crosshairs Checkbox
cross_check = widgets.Checkbox(value=False, description="Green Crosshairs")


def on_cross_change(change):
    """Set crosshair color."""
    if change["new"]:
        nv.set_crosshair_color((0, 1, 0, 1))
    else:
        nv.set_crosshair_color((1, 0, 0, 1))


cross_check.observe(on_cross_change, names="value")

# Wide Crosshairs Checkbox
wide_check = widgets.Checkbox(value=False, description="Wide Crosshairs")


def on_wide_change(change):
    """Set crosshair width."""
    if change["new"]:
        nv.set_crosshair_width(3)
    else:
        nv.set_crosshair_width(1)


wide_check.observe(on_wide_change, names="value")

# Gamma Slider
gamma_slider = widgets.IntSlider(
    value=100,
    min=10,
    max=400,
    step=10,
    description="Gamma",
)


def on_gamma_change(change):
    """Set gamma."""
    nv.set_gamma(change["new"] * 0.01)


gamma_slider.observe(on_gamma_change, names="value")

# Save Bitmap Button
save_bmp_button = widgets.Button(description="Save Bitmap")


def on_save_bmp_clicked(b):
    """Save scene."""
    nv.save_scene("ScreenShot.png")
    with out:
        clear_output(wait=True)
        print("Scene saved as 'ScreenShot.png'")


save_bmp_button.on_click(on_save_bmp_clicked)

# Output widget for messages
out = widgets.Output()

# Organize header controls
header_controls = widgets.VBox(
    [
        invert_check,
        select_check,
        cross_check,
        wide_check,
        gamma_slider,
        save_bmp_button,
    ]
)

# Create the colormap buttons

# Get available colormaps
colormaps = nv.colormaps()
colormap_buttons = []


def create_colormap_button(name):
    """Create a colormap button."""
    btn = widgets.Button(description=name)

    def on_click(b):
        nv.set_colormap(nv.volumes[0].id, name)

    btn.on_click(on_click)
    return btn


colormap_buttons = [create_colormap_button(name) for name in colormaps]

# Organize colormap buttons in a grid
num_cols = 10
num_rows = math.ceil(len(colormap_buttons) / num_cols)
colormap_grid = []

for i in range(num_rows):
    row_buttons = colormap_buttons[i * num_cols : (i + 1) * num_cols]
    colormap_grid.append(widgets.HBox(row_buttons))

colormap_buttons_widget = widgets.VBox(colormap_grid)

# Create the custom colormap input

# Custom Colormap TextArea
cmap_textarea = widgets.Textarea(
    value="""{
  "R": [0, 255, 0],
  "G": [0, 0, 255],
  "B": [0, 0, 0],
  "A": [0, 64, 64],
  "I": [0, 85, 255]
}""",
    description="Custom Colormap",
    layout=widgets.Layout(width="60%", height="100px"),
)

# Custom Colormap Button
custom_button = widgets.Button(description="Custom")


def on_custom_clicked(b):
    """Add the custom colormap to nv."""
    try:
        cmap = json.loads(cmap_textarea.value)
        key = "Custom"
        nv.add_colormap(key, cmap)
        nv.set_colormap(nv.volumes[0].id, key)
    except json.JSONDecodeError:
        with out:
            clear_output(wait=True)
            print("Invalid JSON in custom colormap")


custom_button.on_click(on_custom_clicked)

## Display everything

# Display header controls
display(header_controls)

display(nv)

# Display colormap buttons
display(colormap_buttons_widget)

# Display custom colormap option
display(widgets.HBox([cmap_textarea, custom_button]))

# Display for prints
display(out)